由於畫面上的欄位是透過json產生的
到時候表單送出的欄位應該也是動態產生的
所以這邊也預計透過剛剛的設定檔產生一個紀錄畫面數值的obj
// main.component.ts
export class MainComponent implements OnInit
{
fieldObj!: any;
fieldSettings: FieldSetting[] = [
{
name: 'text1',
cname: '文字欄位1',
inputType: 'text',
placeholder: '請輸入文字',
required: true,
},
{
name: 'number1',
cname: '數字欄位',
inputType: 'number',
placeholder: '請輸入數字',
required: true,
},
{
name: 'tel1',
cname: '電話欄位1',
inputType: 'tel',
placeholder: '請輸入',
required: true,
},
{
name: 'password1',
cname: '密碼欄位1',
inputType: 'password',
placeholder: '請輸入',
required: true,
}
];
constructor() { }
ngOnInit(): void
{
// 用reduce將name作為key值 defaultValue作為Value
this.fieldObj = this.fieldSettings.reduce((acc: any, item) =>
{
acc[item.name] = item.defaultValue || ''; //undefined時補空字串
return acc;
}, {});
}
}
用reduce將name作為key值 defaultValue作為Value
會使用這樣的設計而不是使用陣列
是因為這樣的架構更方便資料送API或者存session
出來的格式會像這個樣子
{
number1:'',
password1:'',
tel1:'',
text1:''
}
到這邊我們擁有了紀錄資料的fieldObj
以及記錄設定檔的fieldSettings
現在問題來了
我們要怎麼把元件綁定到fieldObj上面
一般的寫法可能是用雙向綁定
不過我們這邊至少包了四層
思考了一下其實我們不一定要用雙向綁定
我們將fieldObj傳到元件那一層
在元件上面增加變動事件去變更fieldObj裡面的值
這樣最外面那層的fieldObj裡面的數值就會跟著變動
// main.component.html
<div *ngFor="let fieldSetting of fieldSettings">
<app-field-template [fieldSetting]="fieldSetting" [fieldObj]="fieldObj">
</app-field-template>
{{ fieldObj[fieldSetting.name] }} // 用來確認對應欄位的數值有沒有變動
</div>
// field-template.component.ts
@Input() fieldSetting!: FieldSetting;
@Input() fieldObj!: any; // 多傳fieldObj
// field-template.component.html
<app-field [fieldSetting]="fieldSetting" [fieldObj]="fieldObj"></app-field>
// field.component.ts
@Input() fieldSetting!: FieldSetting;
@Input() fieldObj!: any; // 多傳fieldObj
// field.component.html 以app-base-text為例
<app-base-text
[fieldSetting]="fieldSetting"
[fieldObj]="fieldObj"
></app-base-text>
fieldObj傳到最裡面以後
在欄位原件上做value的綁定
以及偵測元件的變動並將值傳回fieldObj裡面
// base-text.component.html
<div>
<input
type="text"
placeholder="{{ fieldSetting.placeholder || '文字輸入框' }}"
[(ngModel)]="value"
(keyup)="valueChange()"
/>
</div>
// base-text.component.ts
export class BaseTextComponent implements OnInit
{
@Input() fieldSetting!: FieldSetting;
@Input() fieldObj!: any;
value!: string;
constructor() { }
ngOnInit(): void
{
this.value = this.fieldObj[this.fieldSetting.name];
}
valueChange()
{
this.fieldObj[this.fieldSetting.name] = this.value;
}
}
以上大概就是今天的內容
好像還有一些部分想要調整
不過要改的東西太多了 不如改天吧
明天再來繼續調整
今日程式:day06